from EmpVoting.Stat import BaseStatFromFieldCollection

class GroupedExperimentStat(BaseStatFromFieldCollection):

    def __init__(self, groupByField, groupFilter, fieldToGroup, statOp, resultFieldName="", firstBin=None, binSize=None):
        '''
        Constructor
        
        groupByField - name of the field to base groups on
        groupFilter - which groups to include
            supported values are "max", "min", "all". If this is set to "all" 
            then you can optionally set the two bin fields.
        '''
        
        
        self.GroupByField = groupByField
        self.GroupFilter = groupFilter
        self.FieldToGroup = fieldToGroup
        
        self.StatOp = statOp
        
        if resultFieldName != "":
            self.ResultFieldName = resultFieldName
            
        if firstBin != None:
            self.FirstBin = firstBin
        
        if binSize != None:
            self.BinSize = binSize
        
    def Apply(self, expResults):
        groupByList = expResults.__dict__[self.GroupByField]
        fieldToGroupList = expResults.__dict__[self.FieldToGroup]
        
        resultFieldName = ""
        if hasattr(self, "ResultFieldName"):
            resultFieldName = self.ResultFieldName
        else:
            resultFieldName = "group_" + self.GroupFilter + "_" + self.FieldToGroup + "_by_" + self.GroupByField + "_" + self.StatOp            
        
        if self.GroupFilter == "min" or self.GroupFilter == "max":
            expIndex = -1
            
            if self.GroupFilter == "min":
                expIndex = groupByList.index(min(groupByList))
            elif self.GroupFilter == "max":
                expIndex = groupByList.index(max(groupByList))
                
            statResult = self._CalcStatFromList(fieldToGroupList[expIndex], self.StatOp)
            expResults.__dict__[resultFieldName] = statResult 
            
        elif self.GroupFilter == "all":
            useBins = False
            
            groupedDist = {}
            
            if hasattr(self, "FirstBin") and hasattr(self, "BinSize"):
                useBins = True
                
            
            for expIndex in range(0, len(groupByList)):
                curBin = 0
                
                if useBins:
                    curGroupByVal = groupByList[expIndex]
                    curBinIndex = int((curGroupByVal - self.FirstBin) / self.BinSize)
                    curBin = curBinIndex * self.BinSize + self.FirstBin
                    
                else:
                    curBin = groupByList[expIndex]
                    
                if not (curBin in groupedDist):
                    groupedDist[curBin] = []
                    
                groupedDist[curBin].append(fieldToGroupList[expIndex])
                
            for curBin in groupedDist.keys():
                statResult = self._CalcStatFromList(groupedDist[curBin], self.StatOp)
                groupedDist[curBin] = statResult
                
            expResults.__dict__[resultFieldName] = groupedDist
            
        else:
            print("Error: Unknown group filter.")